import logging
import pathlib
import smtplib
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from typing import Sequence

logger = logging.getLogger(__name__)


class SendEmail:
    """mail tool"""

    def __init__(self, host, port, user, password, receivers, subject):
        """

        :param host: smtp server address
        :param port: smtp server port
        :param user: sender's email address
        :param password: email password or authorization code
        :param receivers: recipient email address
        :param subject: emial subject
        :type host: str
        :type port: int
        :type user: str
        :type password: str
        :type receivers: str | Sequence[str]
        :type subject: str
        """
        self.host = host
        self.port = int(port)
        self.user = self.from_addr = user
        self.password = password
        self.to_addrs = receivers
        self.subject = subject
        if port == 25:
            self.smtp = smtplib.SMTP()
        else:
            self.smtp = smtplib.SMTP_SSL()

    @staticmethod
    def create_attach(file):
        """create attachment

        :param file:
        :type file: pathlib.Path
        :return:
        """
        with open(file, 'wb') as fp:
            content = fp.read()
        att = MIMEApplication(content)
        att.add_header('content-disposition', 'attachment', filename=file.name)
        return att

    def create_mail(self, content, file=None):
        """create mail

        :param content: email body
        :param file: email attachment
        :type content: str
        :type file:  | PathLike[str]
        :return:
        """
        msg = MIMEMultipart()
        msg['From'] = self.from_addr
        msg['Subject'] = self.subject
        if isinstance(self.to_addrs, str):
            msg['To'] = self.to_addrs
        elif isinstance(self.to_addrs, (list, tuple)):
            msg['To'] = ', '.join(self.to_addrs)

        # build the email body
        msg.attach(MIMEText(content, 'plain', 'utf-8'))

        # determine whether to send attachments
        filepath = pathlib.Path(file)
        if file and filepath.is_file():
            msg.attach(self.create_attach(filepath))

        return msg

    def send_mail(self, content, file=None):
        """send email

        :param content: email body
        :param file: email attachment
        :type content: str
        :type file:  | PathLike[str]
        :return:
        """
        # create mail
        msg = self.create_mail(content, file)
        # send mail
        try:
            logger.info("--------准备发送测试报告---------")
            self.smtp.connect(self.host, self.port)
            self.smtp.login(self.user, self.password)
            self.smtp.sendmail(self.from_addr, self.to_addrs, msg.as_string())
        except smtplib.SMTPException as e:
            logger.error("--------测试报告发送失败---------")
            logger.exception(e)
        else:
            logger.info("--------测试报告发送完毕---------")
        finally:
            self.smtp.quit()
